Aggregates and Functions
Stateless Functions
Stateless Functions work with fields of one specific class/field.
Functions for Numerics
Expression | Explanation |
---|---|
max(x,y) | Maximum |
min(x,y) | Minimum |
abs(x) | Absolute value |
sqrt(x) | Square root |
log(x) | Natural logarithm (base e ). |
exp(x) | Euler's number e raised to the power of a value |
floor(x) | Largest value that is less than or equal to the argument and is equal to a mathematical integer. |
ceil(x) | Smallest value that is greater than or equal to the argument and is equal to a mathematical integer. |
#Shell format
==> select max(1,23)
>_,TIMESTAMP,SYMBOL,TYPE,"MAX (1, 23)"
0,_,,CUSTOM,23
==> select abs(-10)
>_,TIMESTAMP,SYMBOL,TYPE,ABS (-10)
0,_,,CUSTOM,10
==> select float32(10.1123456789)
>_,TIMESTAMP,SYMBOL,TYPE,FLOAT32 (101123456789E-10)
0,_,,CUSTOM,10.112346
Functions for VARCHAR
Functions for VARCHAR datatype.
Expression | Explanation |
---|---|
length(s) | string length |
uppercase(s) | uppercase string |
lowercase(s) | lowercase string |
reverse(s) | reverse string |
indexof(x, y) | find y in x, return index |
substr(x, start, end) | substring |
toTimestamp(string, format) | parse string into timestamp(ms) |
toTimestampNs(string, format) | parse string into timestamp(ns) |
toTimestamp(string) | parse string into timestamp(ms) (use default Timestamp format* ) |
toTimestampNs(string) | parse string into timestamp(ns) (use default Timestamp format* ) |
#Shell format
==> select length('hello')
>_,TIMESTAMP,SYMBOL,TYPE,LENGTH (hello)
0,_,,CUSTOM,5
==> select uppercase('hello')
>_,TIMESTAMP,SYMBOL,TYPE,UPPERCASE (hello)
0,_,,CUSTOM,HELLO
==> select lowercase('HeLlo')
>_,TIMESTAMP,SYMBOL,TYPE,LOWERCASE (HeLlo)
0,_,,CUSTOM,hello
==> select reversed('hello')
>_,TIMESTAMP,SYMBOL,TYPE,REVERSED (hello)
0,_,,CUSTOM,olleh
==> select indexof('h', 'hello')
>_,TIMESTAMP,SYMBOL,TYPE,"INDEXOF (h, hello)"
0,_,,CUSTOM,-1
==> select substr('Hello, World!', 7, 14)
>_,TIMESTAMP,SYMBOL,TYPE,"SUBSTR (Hello, World!, 7, 14)"
0,_,,CUSTOM,World!
SELECT length(entry.exchangeid) AS length
FROM bittrex
ARRAY JOIN entries IN entry
info
toTimestamp and toTimestampNs are available since 5.6.111+.
info
*
Default format for toTimestamp (and toTimestampNs):
-- Parse timestamp with default format:
select toTimestamp('2016-10-27T16:36:08.993+02:00:00[Europe/Paris]')
select toTimestamp('2016-10-27T16:36:08.993+02:00[Europe/Paris]')
select toTimestamp('2016-10-27T16:36:08.993+020000[Europe/Paris]')
select toTimestamp('2016-10-27T16:36:08.993+0200[Europe/Paris]')
select toTimestamp('2016-10-27T16:36:08.993GMT+1[Europe/Paris]')
select toTimestamp('2016-10-27T16:36:08.993PST[Europe/Paris]')
select toTimestamp('2016-10-27T16:36:08.993[Europe/Paris]')
select toTimestamp('2016-10-27T16:36:08.993+02:00:00')
select toTimestamp('2016-10-27T16:36:08.993Z')
select toTimestamp('2016-10-27T16:36:08.993')
select toTimestampNs('2016-10-27T16:36:08.000993')
select toTimestampNs('2016-10-27T16:36:08.000000993')
select toTimestamp('2016-10-27T16:36:08+0200')
select toTimestamp('2016-10-27T16:36:08')
select toTimestamp('2016-10-01T16:36:08Z')
select toTimestamp('2016-10-27')
select toTimestamp('20161223T163608')
select toTimestamp('20161223T1636')
-- Parse timestamp with specified format:
SELECT toTimestamp('2022-08-27 22:32:02.123', 'yyyy-MM-dd HH:mm:ss.SSS')
SELECT toTimestampNs('2022-08-27 22:32:02.123456789', 'yyyy-MM-dd HH:mm:ss.SSSSSSSSS')
SELECT toTimestamp('2024-08 27 22:32 - 02 123 Europe/Moscow', 'yyyy-MM dd HH:mm - ss SSS v')
Functions for Arrays
Expression | Explanation |
---|---|
empty(arr) | is array empty |
notempty(arr) | is array not empty |
size(arr) | array size |
max(arr) | array maximum |
min(arr) | array minimum |
mean(arr) | array mean |
sum(arr) | array sum |
enumerate(arr) | array indices |
sort(arr) | array sort |
indexof(arr, el) | find index of element |
any(arr) | if any element is true |
all(arr) | if all elements are true |
SELECT
sum(entries.size) AS SUM
FROM bittrex
SELECT
avg(entries.price) AS AVG
FROM bittrex
SELECT sort(entries.price) FROM bittrex
SELECT size(entries.price) FROM bittrex
SELECT
ANY(entries.price > 200)
FROM bittrex
SELECT * FROM bitfinex
WHERE notEmpty(entries[THIS IS deltix.timebase.api.messages.universal.TradeEntry])
Internal Functions
Expression | Explanation |
---|---|
now() | returns the current timestamp as a constant at the moment of the query's execution |
currentTimeMs() | continually returns the current time in milliseconds as the query is being executed, providing a dynamic time value throughout the execution process |
streams() | returns an array of streams with full schema information |
typeOf(expr) | returns actual type of expression or object |
symbols(stream key) | returns an array of symbols in stream |
spaces(stream key) | returns an array of spaces in stream |
stateless_functions() | returns an array of stateless functions supported by QQL |
stateful_functions() | returns an array of stateful functions supported by QQL |
-- Select all streams
SELECT s.key
ARRAY JOIN streams() AS s
-- Select all symbols from securities stream
SELECT s
ARRAY JOIN symbols('securities') AS s
-- Select all stateless functions with arguments and types
SELECT f.id, f.arguments.name, f.arguments.dataType.baseName
ARRAY JOIN STATELESS_FUNCTIONS() as f
-- Count entries grouped by type
select typeof(e), count{}() from KRAKEN
array join this.entries as e
group by typeof(e)
Stateful Functions
Keywords
Time template:
SELECT [RUNNING]
function{arg1: value1, arg2: value2}(arg1, arg2)
FROM stream [TRIGGER/RESET] OVER [EVERY] TIME(interval[, offset])
Count template:
SELECT [RUNNING]
function{arg1: value1, arg2: value2}(arg1, arg2)
FROM stream [TRIGGER] OVER COUNT(100)
- RUNNING - the result is returned for every input message. For example we compute
running max
, it means, that for each message we receivemax
for this message and all previous messages in a group. - OVER [EVERY] TIME(5m) - computes functions separately for each (5 minutes) interval and delivers updates at the end of every (5 minutes) interval. If we add EVERY, we expect empty result for empty 5m intervals when no messages were published.
- OVER TIME(1d, 10h) - computes functions separately for each 1 day interval with 10 hours offset and delivers updates daily at 10:00.
- TRIGGER OVER [EVERY] TIME(5m) - receive function results every 5 minutes and function is computed over the entire stream. If we add EVERY, we expect update for empty 5m intervals when no messages were published.
- OVER COUNT(100) - compute function separately for each 100 messages group and receive update every 100 messages.
- TRIGGER OVER COUNT(100) - compute function over the entire stream, but receive updates every 100 messages.
- RESET - is used to reset function based on provided conditions. For example, reset running calculation for each time period instead of carrying on with the cumulative counting.
caution
OVER TIME
produces interval message only at a time when a new message arrives from a source.
For example, for OVER TIME (1m)
if message for new interval arrives at 10:51:08.458, QQL will produce interval message with timestamp 10:51:00.000 with 8.458 seconds delay.
caution
Offset for OVER TIME(interval[, offset]) is available since 5.6.78
.
Functions Syntax
function{initArg1: value1, initArg2: value2, ...}(argValue1, argValue2)
OR
function{value1, value2, ...}(argValue1, argValue2, ...)
Init
arguments could be passed to function like named args
and also like position arguments in {...} braces. Init
arguments are constant, so you cannot pass here selectors or anything similar. Arguments are passed to function in (...) parentheses as positional arguments.
Examples
- max
- running max
- max over count
- running max over count
message | max(field) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
message | running max(field) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
message | max(field) over count(5) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
message | running max(field) over count(5) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
- max over time
- max over every time
- running max reset over time
- running max over every time
message | max(field) over time(1s) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
message | max(field) over every time(1s) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
message | running max(field) reset over time(1s) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
message | running max(field) over every time(1s) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
- max trigger over count
- max trigger over time
- max trigger over every time
message | max(field) trigger over count(5) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
message | max(field) trigger over time(1m) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
message | max(field) trigger over every time(1s) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
- over time
- reset over time
- trigger over time
-- max price for the entire stream
SELECT
max{} (max(entries.price)) AS MAX
FROM bittrex
-- max for every hour time period
SELECT
max{} (max(entries.price)) AS MAX
FROM bittrex
OVER TIME (1h)
-- max from all prior messages for each message
SELECT
RUNNING
max{} (max(entries.price)) AS MAX
FROM bittrex
-- current and total MAX for every message for the time interval
SELECT RUNNING
max{} (max(entries.price)) AS MAX
FROM bittrex
OVER TIME (10m)
-- max value from prior 10 messages for each interval
SELECT
max{} (max(entries.price)) AS MAX
FROM binance
OVER COUNT (10)
-- every 10 messages returns max from all prior messages
SELECT
max{} (max(entries.price)) AS MAX
FROM binance
TRIGGER OVER COUNT (10)
-- every 10 min returns max from all prior messages
SELECT
max{} (max(entries.price)) AS MAX
FROM bittrex
TRIGGER OVER TIME (10m)
-- returns max from all prior messages for every message, resets every 30 min but does not return a snapshot
SELECT RUNNING
max{} (max(entries.price)) AS MAX
FROM bittrex
RESET OVER TIME (30m)
-- incremental update for every message and a snapshot for every 10 messages
SELECT RUNNING
max{} (max(entries.price)) AS MAX
FROM binance
OVER COUNT (10)
-- select BID and ASK price FROM L2EntryNew
-- cast entries array to L2EntryNew type
-- return max for every selection every 1 min
-- filter by packageType and symbol
WITH
(entries AS array(deltix.timebase.api.messages.universal.L2EntryNew)) AS 'entries',
entries[side == BID].price AS 'bidPrices',
entries[side == ASK].price AS 'askPrices'
SELECT
max{}(max(askPrices)) AS 'highAsk',
max{}(max(bidPrices)) AS 'highBid',
min{}(min(askPrices)) AS 'lowAsk',
min{}(min(bidPrices)) AS 'lowBid'
FROM binance
OVER TIME(1m)
WHERE packageType == PERIODICAL_SNAPSHOT
AND symbol == 'BTC/USDT'
-- one-minute bars based on trades
WITH
entries[THIS IS TradeEntry] AS 'entries'
SELECT
sum{}(sum(entries.size)) AS 'volume',
first{}(entries[0].price) AS 'open',
last{}(entries[-1].price) AS 'close',
max{}(max(entries.price)) AS 'high',
min{}(min(entries.price)) AS 'low'
FROM binance
OVER TIME(1m)
WHERE symbol == 'BTC/USDT' AND size(entries) > 0
-- different price indicators
WITH
entries[THIS IS TradeEntry].price AS 'prices'
SELECT
sma{timePeriod: 1h}(price) AS 'sma',
(bollinger{timeWindow: 1h}(price) AS 'bollinger').*,
cma{}(price) AS 'cma'
FROM bitfinex
ARRAY JOIN prices AS 'price'
OVER TIME(10m)
WHERE symbol == 'BTC/USDT' AND size(entries) > 0
-- simple moving average for Prices for 1 min time period returned every 1 hour for each symbol
SELECT
sma{timePeriod: 1m}(max(entries.price))
FROM bittrex
TRIGGER OVER TIME(1h)
GROUP BY symbol
-- Volume-Weighted Average Price (VWAP)
SELECT sum{}(trade.price * trade.size) / sum{}(trade.size)
FROM bitfinex
ARRAY JOIN entries[this is TradeEntry] as trade
OVER TIME (1m)
WHERE symbol == 'BTCUSD'
-- VWAP cumulative
SELECT sum{}(trade.price * trade.size) / sum{}(trade.size)
FROM bitfinex
ARRAY JOIN entries[this is TradeEntry] as trade
TRIGGER OVER TIME (1m)
WHERE symbol == 'BTCUSD'
-- counts the number of unique FX instruments in the securities stream
SELECT size(collect_unique{}(symbol)) FROM "securities"
where type == "deltix.timebase.api.messages.InstrumentType":FX
-- builds L2 order book with 10 levels size for bittrex BTC/USDT and returns snapshots every 10 seconds
SELECT orderbook{maxDepth: 10}(this.packageType, this.entries)
FROM bittrex
OVER TIME (10s)
WHERE symbol == 'BTC/USDT'
-- builds L2 order book and returns snapshots in Universal format
WITH
orderbook{maxDepth: 10}(this.packageType, this.entries) as book
SELECT
book as entries,
PERIODICAL_SNAPSHOT as packageType
TYPE "deltix.timebase.api.messages.universal.PackageHeader"
FROM BITFINEX
OVER TIME (10s)
WHERE symbol == 'BTC/USDT'
-- builds L3 order book and returns snapshots in Universal format (L3 is supported since 5.6.95+) for each symbol
WITH
orderbook{maxDepth: 10, model: 'L3'}(this.packageType, this.entries) as book
SELECT
book as entries,
PERIODICAL_SNAPSHOT as packageType
TYPE "deltix.timebase.api.messages.universal.PackageHeader"
FROM MBO
OVER TIME (10s)
WHERE size(book) > 0
GROUP BY symbol
-- calculate sum of trade quantities for each day, given that the trading day starts at 15:00 UTC
SELECT
SUM{}(tradeQuantity * -1 if orderEvent:Side == SELL else tradeQuantity)
FROM "ember-messages"
OVER Time(1d, 15h)
WHERE orderStatus IN (COMPLETELY_FILLED, PARTIALLY_FILLED)
AND symbol IN ('BTCUSD')
GROUP BY symbol
List of Functions
ID | Init args | Args | Returns | Description |
---|---|---|---|---|
COUNT | INT64 | counts messages | ||
MAX | BOOLEAN?, INT8?, INT16?, INT32?, INT64?, FLOAT32?, FLOAT64?, DECIMAL64?, TIMESTAMP?, TIMEOFDAY?, VARCHAR? | BOOLEAN?, INT8?, INT16?, INT32?, INT64?, FLOAT32?, FLOAT64?, DECIMAL64?, TIMESTAMP?, TIMEOFDAY?, VARCHAR? | computes maximum value | |
MAX | timePeriod: INT64 | FLOAT64? | FLOAT64? | computes maximum over time window with given timePeriod |
MAX | period: INT64 | FLOAT64? | FLOAT64? | computes maximum over count window with given period |
MIN | BOOLEAN?, INT8?, INT16?, INT32?, INT64?, FLOAT32?, FLOAT64?, DECIMAL64?, TIMESTAMP?, TIMEOFDAY?, VARCHAR? | BOOLEAN?, INT8?, INT16?, INT32?, INT64?, FLOAT32?, FLOAT64?, DECIMAL64?, TIMESTAMP?, TIMEOFDAY?, VARCHAR? | computes minimum value | |
MIN | timePeriod: INT64 | FLOAT64? | FLOAT64? | computes minimum over time window with given timePeriod |
MIN | period: INT64 | FLOAT64? | FLOAT64? | computes minimum over count window with given period |
SUM | INT8?, INT16?, INT32?, INT64?, DECIMAL64? | DECIMAL64? | computes sum of given values | |
SUM | FLOAT32?, FLOAT64? | FLOAT32?, FLOAT64? | computes sum of given values | |
SUM | timePeriod: INT64 | DECIMAL64? | DECIMAL64? | computes sum of values in time window with given time period |
SUM | period: INT32 | DECIMAL64? | DECIMAL64? | computes sum of values in count window with given period |
AVG | INT8?, INT16?, INT32?, INT64?, DECIMAL64? | DECIMAL64? | computes avg of given values | |
AVG | FLOAT32?, FLOAT64? | FLOAT32?, FLOAT64? | computes avg of given values | |
SMA | timePeriod: INT64 | FLOAT64? | FLOAT64? | computes moving average over time window with given timePeriod |
SMA | period: INT64 | FLOAT64? | FLOAT64? | computes moving average over count window with given period |
CMA | FLOAT64? | FLOAT64? | computes cumulative moving average | |
EMA | period: INT32 | FLOAT64? | FLOAT64? | computes exponential moving average with given period |
EMA | factor: FLOAT64 | FLOAT64? | FLOAT64? | computes exponential moving average with given factor |
ADXR | period: INT64 | open, high, low, close, volume (FLOAT64) | ADXRMessage | computes Average Directional Movement Rating indicator (read more) |
ATR | period: INT64 | open, high, low, close, volume (FLOAT64) | FLOAT64 | computes Average True Range (read more) |
BOLLINGER | pointWindow: INT64 or timeWindow: INT64, factor: FLOAT64 | FLOAT64 | BollingerMessage | computes Bollinger Bands (read more) |
KAMA | period: INT64 | FLOAT64 | FLOAT64 | computes Kaufman's Adaptive Moving Average (read more) |
LSMA | pointWindow: INT64 or timeWindow: INT64, useDateTime: BOOLEAN | FLOAT64 | LSMAMessage | computes Least Squares Moving Average (read more) |
MMA | period: INT64 | FLOAT64 | FLOAT64 | computes Modified Moving Average (read more) |
COLLECT_UNIQUE | VARCHAR? | ARRAYS OF VARCHARS | collects and returns an array of unique strings | |
lastNotNull | BOOLEAN?, INT8?, INT16?, INT32?, INT64?, FLOAT32?, FLOAT64?, DECIMAL64?, TIMESTAMP?, TIMEOFDAY?, VARCHAR?, ARRAY? | BOOLEAN?, INT8?, INT16?, INT32?, INT64?, FLOAT32?, FLOAT64?, DECIMAL64?, TIMESTAMP?, TIMEOFDAY?, VARCHAR?, ARRAY? | fills null gaps with previous not null value | |
window | period: INT64 or timePeriod: INT64 | FLOAT64? | ARRAY OF FLOAT64? | builds fixed size (if period is set) or time (if timePeriod is set) window and returns it as an array |
orderBook | maxDepth: INT32, model: VARCHAR ('L1', 'L2' (default), 'L3') | ENUM(PackageType), ARRAY of OBJECT(BaseEntry) | ARRAY of OBJECT(BaseEntry) | builds order book |
statWindow | period: INT64 or timePeriod: INT64 | FLOAT64? | OBJECT(StatWindowMessage), where StatWindowMessage contains: sum, count, sumOfSquares, sumOfAbs, geometricMean, harmonicMean, firstRawMoment, secondRawMoment, thirdRawMoment, forthRawMoment, variance, standardDeviation, median, min, max | calculates statistics over fixed size (if period is set) window or time window (if timePeriod is set). |